package com.example.lj.uav.view;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.ServiceConnection;
import android.graphics.Point;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.amap.api.maps.AMap;
import com.amap.api.maps.model.MyLocationStyle;
import com.dji.mapkit.core.maps.DJIMap;
import com.dji.mapkit.core.models.DJILatLng;
import com.example.lj.uav.MyApplication;
import com.example.lj.uav.R;
import com.example.lj.uav.enums.PayloadErr;
import com.example.lj.uav.service.FlightRecorderService;
import com.example.lj.uav.utils.AlarmUtils;
import com.example.lj.uav.utils.DensityUtil;
import com.example.lj.uav.utils.MyDate;
import com.example.lj.uav.utils.OnUIUtils;
import com.example.lj.uav.utils.PayloadUtils;
import com.example.lj.uav.utils.ScreenShootUtils;
import com.example.lj.uav.utils.TypeUtils;
import com.example.lj.uav.widget.FlightSettingLayout;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import dji.common.flightcontroller.FlightControllerState;
import dji.keysdk.CameraKey;
import dji.keysdk.KeyManager;
import dji.sdk.flightcontroller.FlightController;
import dji.sdk.payload.Payload;
import dji.sdk.products.Aircraft;
import dji.ux.widget.FPVWidget;
import dji.ux.widget.MapWidget;

import static com.example.lj.uav.MyApplication.mPref;

public class ManualFlightActivity extends Activity implements ViewTreeObserver.OnGlobalLayoutListener {

    private Context context;
    private MapWidget mapWidget;
    private ViewGroup parentView;
    private FPVWidget fpvWidget;
    private FPVWidget secondaryFPVWidget;
    private FrameLayout secondaryVideoView;
    private ImageView ivRed;
    private boolean isMapMini = true;

    private int height;
    private int width;
    private int margin;
    private int deviceWidth;
    private int deviceHeight;
    private int myCh4;
    private long errTime;

    private FlightSettingLayout fsl_flightsetting;

    private ServiceConnection serviceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            ((FlightRecorderService) service).setOnRecordListener(new FlightRecorderService.OnRecordListener() {
                @Override
                public void update(int time) {
                    fsl_flightsetting.setFlightTime(time + "s");
                }
            });
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    private FlightController mFlightController;
    private double longitude;
    private double latitude;
    private boolean secondaryShow = false;

    private void initLocation() {
        mFlightController = MyApplication.getFlightControllerInstance();
        if (mFlightController != null) {
            mFlightController.setStateCallback(new FlightControllerState.Callback() {
                @Override
                public void onUpdate(@NonNull FlightControllerState djiFlightControllerCurrentState) {
                    longitude = djiFlightControllerCurrentState.getAircraftLocation().getLongitude();
                    latitude = djiFlightControllerCurrentState.getAircraftLocation().getLatitude();
                    fsl_flightsetting.setFlightTime(djiFlightControllerCurrentState.getFlightTimeInSeconds() + "s");
                }
            });
        }
    }

    private PayloadUtils.CallBack payloadCb;

    private boolean screenShooted = false;

    public void setPayloadCallBack(PayloadUtils.CallBack callBack) {
        payloadCb = callBack;
    }

    private FileOutputStream out = null;

    private BufferedReader mReader;

    public void initPayloadOutput() {
        String PATH_LOGCAT;
        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED)) {
            // 优先保存到SD卡中
            PATH_LOGCAT = Environment.getExternalStorageDirectory()
                    .getAbsolutePath() + File.separator + "heq/payLoad";
        } else {
            // 如果SD卡不存在，就保存到本应用的目录下
            PATH_LOGCAT = context.getFilesDir().getAbsolutePath()
                    + File.separator + "payLoad";
        }
        File file = new File(PATH_LOGCAT);
        if (!file.exists()) {
            file.mkdirs();
        }

        try {
            out = new FileOutputStream(
                    new File(PATH_LOGCAT, "payload-" + MyDate.getTime() + ".csv"));
            isFirstMsg = true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    private boolean isFirstMsg = true;

    private String payloadMsg = "";

    public void setLine(String l) {
        payloadMsg = payloadMsg + l;
    }

    public InputStream getInputStream() {
        return new ByteArrayInputStream(payloadMsg.getBytes());
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.actvity_manualflight);
        ivRed = findViewById(R.id.iv_red_plus);
        context = this;

        mapWidget = (MapWidget) findViewById(R.id.map_widget);
        mapWidget.initAMap(new MapWidget.OnMapReadyListener() {
            @Override
            public void onMapReady(@NonNull DJIMap map) {
                map.setOnMapClickListener(new DJIMap.OnMapClickListener() {
                    @Override
                    public void onMapClick(DJILatLng latLng) {
                        onViewClick(mapWidget);
                    }
                });
            }
        });

        mapWidget.onCreate(savedInstanceState);
        AMap aMap = (AMap) mapWidget.getMap().getMap();

        //初始化定位点样式
        MyLocationStyle myLocationStyle = new MyLocationStyle();
        //连续定位、且将视角移动到地图中心点，定位点依照设备方向旋转，并且会跟随设备移动。（1秒1次定位）如果不设置myLocationType，默认也会执行此种模式。
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);
        //设置连续定位模式下的定位间隔，只在连续定位模式下生效，单次定位模式下不会生效。单位为毫秒。
        myLocationStyle.interval(2000);
        //设置定位蓝点的Style
        aMap.setMyLocationStyle(myLocationStyle);
        aMap.getUiSettings().setMyLocationButtonEnabled(true);
        // 设置为true表示启动显示定位蓝点，false表示隐藏定位蓝点并不进行定位，默认是false。
        aMap.setMyLocationEnabled(true);


        fsl_flightsetting = findViewById(R.id.manualflight_fsl_flightsetting);

        fsl_flightsetting.setTrackVisible(mapWidget.isFlightPathVisible());

        fsl_flightsetting.setOnEditFinnshListener(new FlightSettingLayout.OnEditFinishListener() {
            @Override
            public void onFinish() {
                hideBar();
            }
        });

        fsl_flightsetting.setOnRadarListener(new FlightSettingLayout.OnRadarListener() {
            @Override
            public void onChanged(boolean b) {
                findViewById(R.id.manual_dj_radar).setVisibility(b ? View.VISIBLE : View.GONE);
            }
        });

        fsl_flightsetting.setOnTrackListener(new FlightSettingLayout.OnTrackListener() {
            @Override
            public void onChanged(boolean b) {
                mapWidget.setFlightPathVisible(b);
            }
        });

        findViewById(R.id.manualflight_fl_show).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                fsl_flightsetting.setVisibility(View.VISIBLE);
                fsl_flightsetting.setAnimation(AnimationUtils.makeInAnimation(ManualFlightActivity.this, false));
            }
        });

        findViewById(R.id.v_back).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });

        initPayloadOutput();
        initLocation();

        myCh4 = mPref.getInt("alarm_limit", 0);
        final TextView text_payload_ch4 = findViewById(R.id.manualflight_text_payload_ch4);
        final TextView text_payload_err = findViewById(R.id.manualflight_text_payload_err);
        Aircraft aircraft = (Aircraft) MyApplication.getProductInstance();
        if (aircraft != null) {
            final Payload payload = aircraft.getPayload();
            /**
             * payload消息处理
             */
            if (payload != null) {
                payload.setMessageCallback(new Payload.HintMessageCallback() {
                    @Override
                    public void onGetMessage(String s) {
//                        s = "ch4:150 ppm\r\ntmp:%02d C\r\ntmp1:%02d C\r\ntmp2:%02d C\r\nerr:12\r\n";
                        myCh4 = mPref.getInt("alarm_limit", -1);
                        if (myCh4 < 0) {
                            return;
                        }
                        Log.e("payloadInfo", s);
                        String msg = s.replace("\n", "")
                                .replace("\r", "");
                        if (msg.contains("ch4:")
                                && msg.contains("ppm")
                                && msg.contains("err:")) {
                            //甲烷
                            String ch4 = msg.substring(msg.indexOf("ch4:"), msg.indexOf("ppm") + 3);
                            int c = TypeUtils.toInt(ch4.substring(ch4.indexOf("ch4:") + 4, ch4.indexOf("ppm")));
//                            int c = 200;
                            int air_bg = mPref.getInt("air_bg",0);
                            c = c-air_bg;
                            if (c > myCh4) {
                                OnUIUtils.setTextViewColor(text_payload_ch4,
                                        getResources().getColor(R.color.red));
                                AlarmUtils.playAlarmVideo(context);
                                if (!screenShooted)
                                    screenShooted = ScreenShootUtils.screenShoot(ManualFlightActivity.this);
                            } else {
                                OnUIUtils.setTextViewColor(text_payload_ch4,
                                        getResources().getColor(R.color.forestgreen));
                                AlarmUtils.stopAlarm();
                                screenShooted = false;
                            }
                            OnUIUtils.setTextView(text_payload_ch4, ch4);

                            //错误码
                            Log.e("payloadMsg", "msg=" + msg);
                            Log.e("payloadMsg", "err=" + msg.substring(msg.indexOf("err:") + 4, msg.length()));
                            int e = TypeUtils.toInt(msg.substring(msg.indexOf("err:") + 4, msg.length()));
                            if (e == 0) {
                                OnUIUtils.setTextViewColor(text_payload_err, getResources().getColor(R.color.forestgreen));
                            } else {
                                OnUIUtils.setTextViewColor(text_payload_err, getResources().getColor(R.color.red));
                                if (System.currentTimeMillis() - errTime > 2000) {
                                    OnUIUtils.setToast(PayloadErr.getNameByIndex(e));
                                    errTime = System.currentTimeMillis();
                                }
                            }
                            OnUIUtils.setTextView(text_payload_err, PayloadErr.getNameByIndex(e));
                        } else
                            OnUIUtils.setTextView(text_payload_ch4, msg);

                        if (payloadCb != null)
                            payloadCb.setData(msg);

                        //输出
                        try {
                            if (isFirstMsg) {
                                String[] split = s.split("\r\n");
                                StringBuilder title = new StringBuilder("time")
                                        .append("\",\"")
                                        .append("longitude")
                                        .append("\",\"")
                                        .append("latitude");
                                for (String aSplit : split) {
                                    title.append("\",\"")
                                            .append(aSplit.substring(0, aSplit.indexOf(":")));
                                }
                                setLine(title.toString());
                                isFirstMsg = false;
                            }

                            String replace = s.replace("ch4:", "")
                                    .replace("tmp:", "")
                                    .replace("tmp1:", "")
                                    .replace("tmp2:", "")
                                    .replace("err:", "")
                                    .replace("\r\n", "\",\"");

                            setLine("\r\n" + "" + MyDate.getTime() + "\",\"" + longitude + "\",\"" + latitude + "\",\"" + replace);

                            mReader = new BufferedReader(new InputStreamReader(
                                    getInputStream()), 1024);

                            String line = null;
                            while ((line = mReader.readLine()) != null) {
                                if (line.length() == 0) {
                                    continue;
                                }
                                Log.e("run", line);
                                if (out != null) {
                                    out.write(("\"" + line + "\"" + "\n").getBytes());
                                }
                            }
                            payloadMsg = "";

                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                    }
                });
            }
        }



        height = DensityUtil.dip2px(this, 100);
        width = DensityUtil.dip2px(this, 150);
        margin = DensityUtil.dip2px(this, 12);

        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
        deviceHeight = displayMetrics.heightPixels;
        deviceWidth = displayMetrics.widthPixels;

        parentView = (ViewGroup) findViewById(R.id.root_view);

        fpvWidget = findViewById(R.id.fpv_widget);
        fpvWidget.setSourceCameraNameVisibility(false);
        fpvWidget.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onViewClick(fpvWidget);
            }
        });
        secondaryVideoView = (FrameLayout) findViewById(R.id.secondary_video_view);
        secondaryVideoView.setClickable(true);
        secondaryFPVWidget = findViewById(R.id.secondary_fpv_widget);
        secondaryFPVWidget.setSourceCameraNameVisibility(false);
        secondaryFPVWidget.setSourceCameraSideVisibility(false);
        secondaryVideoView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ResizeAnimation animation;
                if (secondaryShow){
                    animation = new ResizeAnimation(secondaryVideoView,deviceWidth/3*2,deviceHeight/3*2,width,height,0);
                    secondaryShow = false;
                }else{
                    animation = new ResizeAnimation(secondaryVideoView,width,height,deviceWidth/3*2,deviceHeight/3*2,0);
                    secondaryShow = true;
                }
                secondaryVideoView.startAnimation(animation);
            }
        });
        updateSecondaryVideoVisibility();

    }


    @Override
    protected void onResume() {
        super.onResume();
        hideBar();
        mapWidget.onResume();
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        //
        fsl_flightsetting.checkSourseInput();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mapWidget.onPause();

    }


    @Override
    protected void onDestroy() {
        mapWidget.onDestroy();
        super.onDestroy();
        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            out = null;
        }
        if (mFlightController != null) {
            mFlightController.setStateCallback(null);
        }
    }


    @Override
    public void onGlobalLayout() {
        if (isNavigationBarShow(this)) {
            hideBar();
        }
    }

    public boolean isNavigationBarShow(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            Display display = activity.getWindowManager().getDefaultDisplay();
            Point size = new Point();
            Point realSize = new Point();
            display.getSize(size);
            display.getRealSize(realSize);
            boolean result = realSize.y != size.y;
            return realSize.y != size.y;
        } else {
            boolean menu = ViewConfiguration.get(activity).hasPermanentMenuKey();
            boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
            if (menu || back) {
                return false;
            } else {
                return true;
            }
        }
    }


    // Hide both the navigation bar and the status bar.
    private void hideBar() {
        //隐藏虚拟按键，并且全屏
        if (Build.VERSION.SDK_INT < 19) { // lower api
            View v = this.getWindow().getDecorView();
            v.setSystemUiVisibility(View.GONE);
        } else {
            View decorView = getWindow().getDecorView();
            int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                    | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    | View.SYSTEM_UI_FLAG_IMMERSIVE;
            decorView.setSystemUiVisibility(uiOptions);
        }
    }

    private void onViewClick(View view) {
        if (view == fpvWidget && !isMapMini) {
            resizeFPVWidget(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT, 0, 0);
            reorderCameraCapturePanel();
            ResizeAnimation mapViewAnimation = new ResizeAnimation(mapWidget, deviceWidth, deviceHeight, width, height, 0);
            mapWidget.startAnimation(mapViewAnimation);
            isMapMini = true;
        } else if (view == mapWidget && isMapMini) {
            hidePanels();
            resizeFPVWidget(width, height, 0, 12);
            reorderCameraCapturePanel();
            ResizeAnimation mapViewAnimation = new ResizeAnimation(mapWidget, width, height, deviceWidth, deviceHeight, 0);
            mapWidget.startAnimation(mapViewAnimation);
            isMapMini = false;
        }
    }

    private void resizeFPVWidget(int width, int height, int margin, int fpvInsertPosition) {
        RelativeLayout.LayoutParams fpvParams = (RelativeLayout.LayoutParams) fpvWidget.getLayoutParams();
        fpvParams.height = height;
        fpvParams.width = width;
        fpvParams.rightMargin = margin;
        fpvParams.bottomMargin = margin;
        if (isMapMini) {
            fpvParams.addRule(RelativeLayout.CENTER_IN_PARENT, 0);
            fpvParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
            fpvParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
        } else {
            fpvParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
            fpvParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0);
            fpvParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, 0);
        }
        fpvWidget.setLayoutParams(fpvParams);

        parentView.removeView(fpvWidget);
        parentView.addView(fpvWidget, fpvInsertPosition);
    }

    private void reorderCameraCapturePanel() {
        View cameraCapturePanel = findViewById(R.id.CameraCapturePanel);
        parentView.removeView(cameraCapturePanel);
        parentView.addView(cameraCapturePanel, isMapMini ? 9 : 13);
    }

    private void swapVideoSource() {
        if (secondaryFPVWidget.getVideoSource() == FPVWidget.VideoSource.SECONDARY) {
            fpvWidget.setVideoSource(FPVWidget.VideoSource.SECONDARY);
            secondaryFPVWidget.setVideoSource(FPVWidget.VideoSource.PRIMARY);
        } else {
            fpvWidget.setVideoSource(FPVWidget.VideoSource.PRIMARY);
            secondaryFPVWidget.setVideoSource(FPVWidget.VideoSource.SECONDARY);
        }
    }

    private void updateSecondaryVideoVisibility() {
        if (secondaryFPVWidget.getVideoSource() == null) {
            secondaryVideoView.setVisibility(View.GONE);
        } else {
            secondaryVideoView.setVisibility(View.VISIBLE);
        }
    }

    private void hidePanels() {
        KeyManager.getInstance().setValue(CameraKey.create(CameraKey.HISTOGRAM_ENABLED), false, null);
        KeyManager.getInstance().setValue(CameraKey.create(CameraKey.COLOR_WAVEFORM_ENABLED), false, null);

        findViewById(R.id.pre_flight_check_list).setVisibility(View.GONE);
        findViewById(R.id.rtk_panel).setVisibility(View.GONE);
//        findViewById(R.id.spotlight_panel).setVisibility(View.GONE);
        findViewById(R.id.speaker_panel).setVisibility(View.GONE);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mapWidget.onSaveInstanceState(outState);
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mapWidget.onLowMemory();
    }

    private class ResizeAnimation extends Animation {

        private View mView;
        private int mToHeight;
        private int mFromHeight;

        private int mToWidth;
        private int mFromWidth;
        private int mMargin;

        private ResizeAnimation(View v, int fromWidth, int fromHeight, int toWidth, int toHeight, int margin) {
            mToHeight = toHeight;
            mToWidth = toWidth;
            mFromHeight = fromHeight;
            mFromWidth = fromWidth;
            mView = v;
            mMargin = margin;
            setDuration(300);
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            float height = (mToHeight - mFromHeight) * interpolatedTime + mFromHeight;
            float width = (mToWidth - mFromWidth) * interpolatedTime + mFromWidth;
            RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mView.getLayoutParams();
            p.height = (int) height;
            p.width = (int) width;
            p.rightMargin = mMargin;
            p.bottomMargin = mMargin;
            mView.requestLayout();
        }
    }

    public void showRedPlus() {
        ivRed.setVisibility(View.VISIBLE);
    }

    public void hideRedPlus() {
        ivRed.setVisibility(View.GONE);
    }
}
